package com.spl.seriallibrary.util;

public class SerialPortTools {

    private static char[] CrcTbl = {0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41,
            0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81,
            0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0,
            0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01,
            0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
            0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281,
            0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1,
            0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700,
            0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741,
            0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980,
            0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0,
            0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};

    public static byte[] CRC8_TAB = {0x00, 0x5e, (byte) 0xbc, (byte) 0xe2, 0x61, 0x3f, (byte) 0xdd, (byte) 0x83,
            (byte) 0xc2, (byte) 0x9c, 0x7e, 0x20, (byte) 0xa3, (byte) 0xfd, 0x1f, 0x41, (byte) 0x9d, (byte) 0xc3, 0x21,
            0x7f, (byte) 0xfc, (byte) 0xa2, 0x40, 0x1e, 0x5f, 0x01, (byte) 0xe3, (byte) 0xbd, 0x3e, 0x60, (byte) 0x82,
            (byte) 0xdc, 0x23, 0x7d, (byte) 0x9f, (byte) 0xc1, 0x42, 0x1c, (byte) 0xfe, (byte) 0xa0, (byte) 0xe1,
            (byte) 0xbf, 0x5d, 0x03, (byte) 0x80, (byte) 0xde, 0x3c, 0x62, (byte) 0xbe, (byte) 0xe0, 0x02, 0x5c,
            (byte) 0xdf, (byte) 0x81, 0x63, 0x3d, 0x7c, 0x22, (byte) 0xc0, (byte) 0x9e, 0x1d, 0x43, (byte) 0xa1,
            (byte) 0xff, 0x46, 0x18, (byte) 0xfa, (byte) 0xa4, 0x27, 0x79, (byte) 0x9b, (byte) 0xc5, (byte) 0x84,
            (byte) 0xda, 0x38, 0x66, (byte) 0xe5, (byte) 0xbb, 0x59, 0x07, (byte) 0xdb, (byte) 0x85, 0x67, 0x39,
            (byte) 0xba, (byte) 0xe4, 0x06, 0x58, 0x19, 0x47, (byte) 0xa5, (byte) 0xfb, 0x78, 0x26, (byte) 0xc4,
            (byte) 0x9a, 0x65, 0x3b, (byte) 0xd9, (byte) 0x87, 0x04, 0x5a, (byte) 0xb8, (byte) 0xe6, (byte) 0xa7,
            (byte) 0xf9, 0x1b, 0x45, (byte) 0xc6, (byte) 0x98, 0x7a, 0x24, (byte) 0xf8, (byte) 0xa6, 0x44, 0x1a,
            (byte) 0x99, (byte) 0xc7, 0x25, 0x7b, 0x3a, 0x64, (byte) 0x86, (byte) 0xd8, 0x5b, 0x05, (byte) 0xe7,
            (byte) 0xb9, (byte) 0x8c, (byte) 0xd2, 0x30, 0x6e, (byte) 0xed, (byte) 0xb3, 0x51, 0x0f, 0x4e, 0x10,
            (byte) 0xf2, (byte) 0xac, 0x2f, 0x71, (byte) 0x93, (byte) 0xcd, 0x11, 0x4f, (byte) 0xad, (byte) 0xf3, 0x70,
            0x2e, (byte) 0xcc, (byte) 0x92, (byte) 0xd3, (byte) 0x8d, 0x6f, 0x31, (byte) 0xb2, (byte) 0xec, 0x0e, 0x50,
            (byte) 0xaf, (byte) 0xf1, 0x13, 0x4d, (byte) 0xce, (byte) 0x90, 0x72, 0x2c, 0x6d, 0x33, (byte) 0xd1,
            (byte) 0x8f, 0x0c, 0x52, (byte) 0xb0, (byte) 0xee, 0x32, 0x6c, (byte) 0x8e, (byte) 0xd0, 0x53, 0x0d,
            (byte) 0xef, (byte) 0xb1, (byte) 0xf0, (byte) 0xae, 0x4c, 0x12, (byte) 0x91, (byte) 0xcf, 0x2d, 0x73,
            (byte) 0xca, (byte) 0x94, 0x76, 0x28, (byte) 0xab, (byte) 0xf5, 0x17, 0x49, 0x08, 0x56, (byte) 0xb4,
            (byte) 0xea, 0x69, 0x37, (byte) 0xd5, (byte) 0x8b, 0x57, 0x09, (byte) 0xeb, (byte) 0xb5, 0x36, 0x68,
            (byte) 0x8a, (byte) 0xd4, (byte) 0x95, (byte) 0xcb, 0x29, 0x77, (byte) 0xf4, (byte) 0xaa, 0x48, 0x16,
            (byte) 0xe9, (byte) 0xb7, 0x55, 0x0b, (byte) 0x88, (byte) 0xd6, 0x34, 0x6a, 0x2b, 0x75, (byte) 0x97,
            (byte) 0xc9, 0x4a, 0x14, (byte) 0xf6, (byte) 0xa8, 0x74, 0x2a, (byte) 0xc8, (byte) 0x96, 0x15, 0x4b,
            (byte) 0xa9, (byte) 0xf7, (byte) 0xb6, (byte) 0xe8, 0x0a, 0x54, (byte) 0xd7, (byte) 0x89, 0x6b, 0x35};

    public static byte calcCrc8(byte[] data, int offset, int len) {
        return calcCrc8(data, offset, len, (byte) 0);
    }

    public static byte calcCrc8(byte[] data, int offset, int len, byte preval) {
        byte ret = preval;
        for (int i = offset; i < (offset + len); ++i) {
            ret = CRC8_TAB[(0x00ff & (ret ^ data[i]))];
        }
        return ret;
    }

    public static byte calculateLock(String string) {
        if (string.substring(0, 1).equalsIgnoreCase("Z")) {//主柜
            if (Integer.parseInt(string.substring(1, 3)) == 99) {
                return 8;
            }
            //18路双开，绵阳要求12路锁控板去掉CH13控制门磁功能，改为开锁
            else if (Integer.parseInt(string.substring(1, 3)) == 0) {
                return 0x0d;
            } else {
                return (byte) Integer.parseInt(string.substring(1, 3));
            }
        } else {
            return (byte) Integer.parseInt(string.substring(1, 3));
            /**
             * 绵阳2路锁编号01、02
             */
        }
    }

    public static byte calculateBoard(String string) {
        String str = string.substring(0, 1);
        if (str.equals("Z")) {
            return 0x00;
        } else if (str.equals("A")) {
            return 0x01;
        } else if (str.equals("B")) {
            return 0x02;
        } else if (str.equals("C")) {
            return 0x03;
        } else if (str.equals("D")) {
            return 0x04;
        } else if (str.equals("E")) {
            return 0x05;
        } else if (str.equals("F")) {
            return 0x06;
        } else if (str.equals("G")) {
            return 0x07;
        } else if (str.equals("H")) {
            return 0x08;
        } else if (str.equals("I")) {
            return 0x09;
        } else if (str.equals("J")) {
            return 0x0a;
        } else if (str.equals("K")) {
            return 0x0b;
        } else if (str.equals("L")) {
            return 0x0c;
        } else {
            return 0x0f;
        }
    }

    public static byte getBoardId(String string) {
        String str = string.substring(0, 1);
        if (str.equals("Z")) {
            return 0x01;
        } else if (str.equals("A")) {
            return 0x02;
        } else if (str.equals("B")) {
            return 0x03;
        } else if (str.equals("C")) {
            return 0x04;
        } else if (str.equals("D")) {
            return 0x05;
        } else if (str.equals("E")) {
            return 0x06;
        } else if (str.equals("F")) {
            return 0x07;
        } else if (str.equals("G")) {
            return 0x08;
        } else if (str.equals("H")) {
            return 0x09;
        } else if (str.equals("I")) {
            return 0x0a;
        } else if (str.equals("J")) {
            return 0x0b;
        } else if (str.equals("K")) {
            return 0x0c;
        } else if (str.equals("L")) {
            return 0x0d;
        } else {
            return 0x0e;
        }
    }

    public static String byteToHexStr(int length, byte[] msg) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            byte b = msg[i];
            String str = Integer.toHexString(0xFF & b);
            if (str.length() == 1) {
                str = "0" + str;
            } else {
                str = "" + str;
            }

            sb.append(str);
        }
        return sb.toString();
    }

    public static byte[] subBytes(byte[] src, int begin, int count) {
        if (count < 0) {
            return new byte[]{0x09};
        }
        byte[] bs = new byte[count];
        for (int i = begin; i < begin + count; i++) {
            bs[i - begin] = src[i];
        }
        return bs;
    }

    public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
        byte[] byte_3 = new byte[byte_1.length + byte_2.length];
        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
        return byte_3;
    }

    /**
     * 计算crc16
     *
     * @param data 代计算的字节
     * @return crc byte[]
     */
    public static byte[] calcCrcBytes(byte[] data) {
        int crc = crcVal(data);
        String hexIdCrc = Integer.toHexString(crc).substring(0, 4);
        return hexStringToByteArray(hexIdCrc);
    }

    public static byte[] hexStringToByteArray(String s) {
        if (s.length() < 2) {
            s = "0" + s;
        }
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    /**
     * 查表法计算 CRC-16
     *
     * @param data 代计算的字节
     */
    private static int crcVal(byte[] data) {
        int Index;
        int nCRCData;
        nCRCData = 0xffff;
        for (int i = 0; i < data.length; i++) {
            Index = nCRCData >> 8;
            Index = Index ^ (data[i] & 0x00ff);
            nCRCData = (nCRCData ^ CrcTbl[Index]) & 0x00ff;
            nCRCData = (nCRCData << 8) | (CrcTbl[Index] >> 8);
        }
        return (nCRCData >> 8 | nCRCData << 8);
    }


    public static byte getXor(byte[] datas) {
        byte temp = datas[0];
        for (int i = 1; i < datas.length; i++) {
            temp ^= datas[i];
        }
        return temp;
    }
}
